package 打牢基础30天.day04.my;

import javax.xml.transform.Result;
import java.util.HashMap;

/**
 * @Author yaya
 * @Create 2024/6/14 16:36
 * Description:node中有一个round指针，指向随机的一个node， 要将这些node复制下来，并且随机的指针也要复制
 */
public class Code06_CopyListWithRandom {

    public static class Node {
        public int value;
        public Node next;
        public Node rand;

        Node(int data) {
            this.value = data;
        }
    }

    /**
     * 使用hashmap来存储，key为原来的node， value为复制的node，
     * 复制的node需要的随机node可以通过key指向的randNode为key的value来复制
     *
     * @return
     */
    public static Node copyListWithRandom1(Node head) {
        HashMap<Node, Node> hashMap = new HashMap<>();
        Node temp = head;
        // 先将复制的值放入hashMap中
        while (temp != null) {
            hashMap.put(temp, new Node(temp.value));
            temp = temp.next;
        }

        // 通过hashMap获取对应的next,rand值
        temp = head;
        while (temp != null) {
            hashMap.get(temp).next = hashMap.get(temp.next);
            hashMap.get(temp).rand = hashMap.get(temp.rand);
            temp = temp.next;
        }

        return hashMap.get(head);
    }

    /**
     * 使用逻辑空间存储head的复制节点
     * 将node的复制节点放在对应节点的下一个位置，这样就可以通过对应节点.next获取复制节点的.rand
     *
     * @param head
     */
    public static Node copyListWithRandom2(Node head) {
        if (head == null) {
            return null;
        }
        // 在每个节点后添加复制节点
        Node temp = head;
        Node next = null;
        while (temp != null){
            next = temp.next;
            temp.next = new Node(temp.value);
            temp.next.next = next;
            temp = next;
        }

        // 设置复制节点的rand指针
        temp = head;
        while (temp != null){
            next = temp.next.next;
            temp.next.rand = temp.rand == null ? null : temp.rand.next;
            temp = next;
        }

        // 分离节点；使得这个链表分为原始链表和复制链表
        Node res = head.next;
        Node nodeC = null;
        temp = head;
        while (temp != null){
            next = temp.next.next;
            nodeC = temp.next;
            temp.next = next;
            nodeC.next = next != null ? next.next : null;
            temp = next;
        }
        return res;

    }


    public static void printRandLinkedList(Node head) {
        Node cur = head;
        System.out.print("order: ");
        while (cur != null) {
            System.out.print(cur.value + " ");
            cur = cur.next;
        }
        System.out.println();
        cur = head;
        System.out.print("rand:  ");
        while (cur != null) {
            System.out.print(cur.rand == null ? "- " : cur.rand.value + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head = null;
        Node res1 = null;
        Node res2 = null;
        printRandLinkedList(head);
        res1 = copyListWithRandom1(head);
        printRandLinkedList(res1);
        res2 = copyListWithRandom2(head);
        printRandLinkedList(res2);
        printRandLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(4);
        head.next.next.next.next = new Node(5);
        head.next.next.next.next.next = new Node(6);

        head.rand = head.next.next.next.next.next; // 1 -> 6
        head.next.rand = head.next.next.next.next.next; // 2 -> 6
        head.next.next.rand = head.next.next.next.next; // 3 -> 5
        head.next.next.next.rand = head.next.next; // 4 -> 3
        head.next.next.next.next.rand = null; // 5 -> null
        head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4

        printRandLinkedList(head);
        res1 = copyListWithRandom1(head);
        printRandLinkedList(res1);
        res2 = copyListWithRandom2(head);
        printRandLinkedList(res2);
        printRandLinkedList(head);
        System.out.println("=========================");

    }

}
